#include <iostream>
#include <memory>
#include <functional>

// unique_ptr模拟实现
template <class T>
struct PointerDeleter
{
    void operator()(const T *ptr)
    {
        if (ptr)
        {
            delete ptr;
            ptr = nullptr;
        }
    }
};
template <class T, class Deleter = PointerDeleter<T>>
class unique_ptr
{
public:
    explicit unique_ptr(T *p = nullptr)
        : ptr(p)
    {
    }

    ~unique_ptr()
    {
        deleter(ptr);
    }

    unique_ptr(const unique_ptr &) = delete;
    unique_ptr &operator=(const unique_ptr &) = delete;

    unique_ptr(unique_ptr &&other) noexcep
        : ptr(other.ptr),
          deleter(std::move(other.ptr))
    {
        other.ptr = nullptr;
    }

    // unique_ptr &operator=(unique_ptr &&other) noexcept
    // {
    //     if (this != &other)
    //     {
    //         deleter(ptr);
    //         ptr = other.ptr;
    //         deleter = std::move(other.deleter);
    //         other.ptr = nullptr;
    //     }
    //     return *this;
    // }

    unique_ptr &operator=(unique_ptr &&other) noexcept
    {
        std::swap(ptr, other.ptr);
        return *this;
    }

    operator bool() const
    {
        return ptr != nullptr;
    }

    T &operator*() const { return *ptr; }
    T *operator->() const { return ptr; }

    T *get() { return ptr; }

    T *release()
    {
        T *tmp = ptr;
        ptr = nullptr;
        return tmp;
    }

    // void reset(T *p = nullptr)
    // {
    //     deleter(ptr);
    //     ptr = p;
    // }

    void reset(T *p = nullptr)
    {
        unique_ptr<T, Deleter>().swap(this);
        ptr = p;
    }

    void swap(unique_ptr &p)
    {
        std::swap(ptr, p.ptr);
    }

private:
    T *ptr;
    Deleter deleter;
};

// 传统的策略模式的实现
// 抽象策略类,提供一个接口
class Hurt
{
public:
    virtual void blood() = 0;
};

// 具体的策略实现类
class AdcHurt : public Hurt
{
public:
    void blood() override
    {
    std:
        std::cout << "ADC hurt,Blood loss" << std::endl;
    }
};

class ApcHurt : public Hurt
{
public:
    void blood() override
    {
    std:
        std::cout << "APC hurt,Blood loss" << std::endl;
    }
};

// 类指针方式
// 环境角色类,游戏角色战士,传入一个策略指针参数
class Soldier
{
public:
    Soldier(std::shared_ptr<Hurt> hurt)
        : m_hurt(hurt)
    {
    }

    // 在不同的策略下,该游戏角色表现出不同的攻击
    void attack()
    {
        m_hurt->blood();
    }

private:
    std::shared_ptr<Hurt> m_hurt;
};

// 策略标签+简单工厂模式+策略模式
// 定义策略标签
typedef enum
{
    Hurt_Type_ADC,
    Hurt_Type_APC,
    Hurt_Type_NUM,
} HurtType;

// 环境角色类,游戏角色法师,传入一个策略标签参数
class Mage
{
public:
    Mage(HurtType type)
    {
        switch (type)
        {
        case Hurt_Type_ADC:
            m_pHurt = std::make_shared<AdcHurt>();
            break;
        case Hurt_Type_APC:
            m_pHurt = std::make_shared<ApcHurt>();
            break;
        default:
            break;
        }
    }

    void attack()
    {
        m_pHurt->blood();
    }

private:
    std::shared_ptr<Hurt> m_pHurt;
};

// 模版实现
// 游戏角色类,游戏角色弓弩手,实现模板传递策略
template <class T>
class Archer
{
public:
    void attack()
    {
        m_hurt.blood();
    }

private:
    T m_hurt;
};

int main()
{
    // 传入策略类指针
    Soldier soldier(std::make_shared<AdcHurt>());
    soldier.attack();

    // 传入策略标签,具体策略对象的创建在上下文环境Context中实现
    std::shared_ptr<Mage> pMage = std::make_shared<Mage>(HurtType::Hurt_Type_ADC);
    pMage->attack();

    // 采用模板实现
    Archer<ApcHurt> *arc = new Archer<ApcHurt>;
    arc->attack();
    delete arc;
    arc = nullptr;

    // 基于智能指针的模板
    std::shared_ptr<Archer<AdcHurt>> pArc = std::make_shared<Archer<AdcHurt>>();
    pArc->attack();

    return 0;
}

// // 使用函数指针实现策略模式
// void adcHurt()
// {
//     std::cout << "ADC Hurt" << std::endl;
// }

// void apcHurt()
// {
//     std::cout << "APC Hurt" << std::endl;
// }

// // 环境角色类， 使用传统的函数指针
// class Soldier
// {
// public:
//     typedef void (*Function)();

//     Soldier(Function fun) : m_fun(fun)
//     {
//     }

//     void attack()
//     {
//         m_fun();
//     }

// private:
//     Function m_fun;
// };

// // 环境角色类， 使用std::function<>
// class Mage
// {
// public:
//     typedef std::function<void()> Function;

//     Mage(Function fun) : m_fun(fun)
//     {
//     }

//     void attack()
//     {
//         m_fun();
//     }

// private:
//     Function m_fun;
// };

// int main()
// {
//     // 函数指针实现
//     Soldier *soldier = new Soldier(apcHurt);
//     soldier->attack();
//     delete soldier;
//     soldier = nullptr;

//     // std::function实现
//     std::shared_ptr<Mage> pMage = std::make_shared<Mage>(adcHurt);
//     pMage->attack();

//     return 0;
// }